home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / utility1 / gsview08.zip / CLIP.C next >
C/C++ Source or Header  |  1993-07-06  |  38KB  |  1,425 lines

  1. /*
  2.  * clip.c --    Clipboard and EPS operations for GSVIEW.EXE, 
  3.  *              a graphical interface for MS-Windows Ghostscript
  4.  * Copyright (C) 1993  Russell Lang
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *   Author: Russell Lang
  21.  * Internet: rjl@monu1.cc.monash.edu.au
  22.  */
  23.  
  24. #define STRICT
  25. #include <windows.h>
  26. #include <windowsx.h>
  27. #include <commdlg.h>
  28. #include <shellapi.h>
  29. #include <mmsystem.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <dir.h>
  35. #include <io.h>
  36. #define NeedFunctionPrototypes 1
  37. #include "ps.h"
  38. #include "gsview.h"
  39.  
  40. #include <time.h>
  41.  
  42. #define COPY_BUF_SIZE 16384u
  43.  
  44. /* Write data to file - blocks > 64k permitted */
  45. long
  46. hwrite(HFILE hf, const void _huge *hpvBuffer, long cbBuffer)
  47. {
  48. DWORD count;
  49. long written, done;
  50. char _huge *hp;
  51.     if (is_win31)
  52.         return _hwrite(hf, hpvBuffer, cbBuffer);
  53.     done = 0;
  54.     hp = (char _huge *)hpvBuffer;
  55.     while (cbBuffer > 0) {
  56.         count = min( min(32768UL, cbBuffer), (DWORD)(65536UL-OFFSETOF(hp)) );
  57.         written = _lwrite(hf, hp, (UINT)count);
  58.         if (written == (long)HFILE_ERROR)
  59.         return (long)HFILE_ERROR;
  60.         done += written;
  61.         cbBuffer -= written;
  62.         hp += written;
  63.     }
  64.     return done;
  65. }
  66.  
  67. /* return number of bytes per line, rounded up to multiple of 4 bytes */
  68. LONG
  69. dib_bytewidth(LPBITMAPINFOHEADER pbmih)
  70. {
  71.  return (((pbmih->biWidth * pbmih->biBitCount + 31) & ~31) >> 3);
  72. }
  73.  
  74. /* return number of colors in color table */
  75. UINT
  76. dib_pal_colors(LPBITMAPINFOHEADER pbmih)
  77. {
  78. int bits_per_pixel = pbmih->biPlanes * pbmih->biBitCount;
  79.     if (bits_per_pixel != 24) {
  80.         if (pbmih->biSize == sizeof(BITMAPCOREHEADER)) {
  81.         return 1<<bits_per_pixel;
  82.         }
  83.         else {
  84.         return (pbmih->biClrUsed) ? (UINT)(pbmih->biClrUsed) : 1<<bits_per_pixel;
  85.         }
  86.     }
  87.     return 0;
  88. }
  89.  
  90. /* copy a DIB from the clipboard to a file */
  91. void
  92. clip_to_file(void)
  93. {
  94. HGLOBAL hglobal;
  95. LPBITMAPINFOHEADER pbmih;
  96. BITMAPFILEHEADER bmfh;
  97. UINT palcolors;
  98. UINT palsize;
  99. DWORD bitmap_size;
  100. BYTE _huge *lpBits;
  101. static char output[MAXSTR];
  102. HFILE hfile;
  103.     if (!OpenClipboard(hwndimg)) {
  104.         play_sound(SOUND_ERROR);
  105.         return;
  106.     }
  107.     if (!IsClipboardFormatAvailable(CF_DIB)) {
  108.         CloseClipboard();
  109.         play_sound(SOUND_ERROR);
  110.         return;
  111.     }
  112.     hglobal = (HGLOBAL)GetClipboardData(CF_DIB);
  113.     pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  114.     palcolors = dib_pal_colors(pbmih);
  115.     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  116.         palsize = palcolors * sizeof(RGBTRIPLE); 
  117.     else
  118.         palsize = palcolors * sizeof(RGBQUAD);
  119.     bitmap_size = (DWORD)pbmih->biHeight *  dib_bytewidth(pbmih);
  120.  
  121.     bmfh.bfType = ('M'<<8) | 'B';
  122.     bmfh.bfReserved1 = 0;
  123.     bmfh.bfReserved2 = 0;
  124.     bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + pbmih->biSize + palsize;
  125.     bmfh.bfSize = bmfh.bfOffBits + bitmap_size;
  126.  
  127.     if ( getfilename(output, SAVE, FILTER_BMP, NULL, IDS_TOPICEDIT)
  128.         && ((hfile = _lcreat(output, 0)) != HFILE_ERROR) ) {
  129.         hwrite(hfile, &bmfh, sizeof(BITMAPFILEHEADER));
  130.         hwrite(hfile, pbmih, pbmih->biSize + palsize);
  131.         lpBits =  ((BYTE _huge *)pbmih) + pbmih->biSize + palsize;
  132.         hwrite(hfile, lpBits, bitmap_size);
  133.         _lclose(hfile);
  134.     }
  135.     GlobalUnlock(hglobal);
  136.     CloseClipboard();
  137. }
  138.  
  139. /* convert bitmap (DIB or DDB) in clipboard to */
  140. /* CF_DIB, CF_BITMAP and CF_PALETTE */
  141. void
  142. clip_convert(void)
  143. {
  144.     if (!OpenClipboard(hwndimg)) {
  145.         play_sound(SOUND_ERROR);
  146.         return;
  147.     }
  148.     if (IsClipboardFormatAvailable(CF_DIB)) {
  149.         if (!IsClipboardFormatAvailable(CF_PALETTE))
  150.         clip_add_palette();
  151.         if (!IsClipboardFormatAvailable(CF_BITMAP))
  152.             clip_add_ddb();
  153.     }
  154.     else {
  155.         if (IsClipboardFormatAvailable(CF_BITMAP)) {
  156.         clip_add_dib();
  157.             if (!IsClipboardFormatAvailable(CF_PALETTE))
  158.             clip_add_palette();
  159.         }
  160.         else 
  161.         play_sound(SOUND_ERROR);
  162.     }
  163.     CloseClipboard();
  164. }
  165.  
  166. /* Read DIB from the clipboard, create PALETTE and add to clipboard */
  167. void
  168. clip_add_palette(void)
  169. {
  170. HGLOBAL hglobal;
  171. LPBITMAPINFOHEADER pbmih;
  172. UINT palcolors;
  173. UINT palsize;
  174. int i;
  175. LPLOGPALETTE logpalette;
  176. HPALETTE hpalette;
  177. RGBQUAD FAR *prgbquad;
  178. RGBTRIPLE FAR *prgbtriple;
  179.  
  180.     if (!IsClipboardFormatAvailable(CF_DIB)) {
  181.         play_sound(SOUND_ERROR);
  182.         return;
  183.     }
  184.     hglobal = (HGLOBAL)GetClipboardData(CF_DIB);
  185.     pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  186.     palcolors = dib_pal_colors(pbmih);
  187.     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  188.         palsize = palcolors * sizeof(RGBTRIPLE); 
  189.     else
  190.         palsize = palcolors * sizeof(RGBQUAD);
  191.     hpalette = (HPALETTE)NULL;
  192.     if (palsize) {
  193.         /* create palette to match DIB */
  194.         logpalette = (LPLOGPALETTE) malloc( sizeof(LOGPALETTE) + 
  195.         palcolors * sizeof(PALETTEENTRY) );
  196.         if (logpalette == (LPLOGPALETTE)NULL) {
  197.         GlobalUnlock(hglobal);
  198.         play_sound(SOUND_ERROR);
  199.         return;
  200.         }
  201.         logpalette->palVersion = 0x300;
  202.         logpalette->palNumEntries = palcolors;
  203.         prgbquad = (RGBQUAD FAR *)(((BYTE _huge *)pbmih) + pbmih->biSize);
  204.         if (pbmih->biSize == sizeof(BITMAPCOREHEADER)) {
  205.         /* OS2 format */
  206.             prgbtriple = (RGBTRIPLE FAR *)prgbquad;
  207.             for (i=0; i<palcolors; i++) {
  208.                 logpalette->palPalEntry[i].peFlags = 0;
  209.             logpalette->palPalEntry[i].peRed   = prgbtriple[i].rgbtRed;
  210.             logpalette->palPalEntry[i].peGreen = prgbtriple[i].rgbtGreen;
  211.             logpalette->palPalEntry[i].peBlue  = prgbtriple[i].rgbtBlue;
  212.             }
  213.         }
  214.         else {
  215.         /* Windows Format */
  216.             for (i=0; i<palcolors; i++) {
  217.                 logpalette->palPalEntry[i].peFlags = 0;
  218.             logpalette->palPalEntry[i].peRed   = prgbquad[i].rgbRed;
  219.             logpalette->palPalEntry[i].peGreen = prgbquad[i].rgbGreen;
  220.             logpalette->palPalEntry[i].peBlue  = prgbquad[i].rgbBlue;
  221.             }
  222.         }
  223.         hpalette = CreatePalette(logpalette);
  224.         free((void *)logpalette);
  225.         SetClipboardData(CF_PALETTE, hpalette);
  226.     }
  227.     GlobalUnlock(hglobal);
  228. }
  229.  
  230.  
  231. /* Read DIB from the clipboard, convert to DDB and add to clipboard */
  232. void
  233. clip_add_ddb(void)
  234. {
  235. HGLOBAL hglobal;
  236. LPBITMAPINFOHEADER pbmih;
  237. UINT palcolors;
  238. UINT palsize;
  239. HPALETTE hpalette;
  240. HDC hdc;
  241. HBITMAP hbitmap;
  242.  
  243.     hglobal = (HGLOBAL)GetClipboardData(CF_DIB);
  244.     pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  245.     palcolors = dib_pal_colors(pbmih);
  246.     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  247.         palsize = palcolors * sizeof(RGBTRIPLE); 
  248.     else
  249.         palsize = palcolors * sizeof(RGBQUAD);
  250.  
  251.     hdc = GetDC(hwndimg);
  252.     hpalette = GetClipboardData(CF_PALETTE);
  253.     if (hpalette) {
  254.         SelectPalette(hdc,hpalette,NULL);
  255.         RealizePalette(hdc);
  256.     }
  257.     hbitmap = CreateDIBitmap(hdc, pbmih, CBM_INIT,
  258.         ((BYTE _huge *)pbmih) + pbmih->biSize + palsize,
  259.         (LPBITMAPINFO)pbmih, DIB_RGB_COLORS);
  260.     ReleaseDC(hwndimg, hdc);
  261.     GlobalUnlock(hglobal);
  262.     SetClipboardData(CF_BITMAP, hbitmap);
  263. }
  264.  
  265. /* make a DIB from a BITMAP in the clipboard */
  266. /* GetDIBits won't work for 4 plane or 4 bit/pixel bitmaps */
  267. /* clipboard must be open */
  268. HGLOBAL 
  269. make_dib(void)
  270. {
  271. LPBITMAPINFOHEADER pbmih;
  272. LPBITMAPINFO pbmi;
  273. BYTE FAR *lpBits;
  274. HBITMAP hbitmap;
  275. UINT palcolors;
  276. UINT palsize;
  277. UINT byte_width;
  278. DWORD bitmap_size;
  279. HGLOBAL hglobal;
  280. HDC hdc;
  281. HDC hdc_bit;
  282. BITMAP bm;
  283. PALETTEENTRY *pe;
  284. int i;
  285.     hbitmap = GetClipboardData(CF_BITMAP);
  286.     hdc = GetDC((HWND)NULL);
  287.     hdc_bit = CreateCompatibleDC(hdc);
  288.     ReleaseDC((HWND)NULL,hdc);
  289.     GetObject(hbitmap, sizeof(BITMAP), &bm);
  290.     if (bm.bmPlanes == 4) {
  291.         HBITMAP hbitmap_new, hbitmap_old;
  292.         HDC hdc_new;
  293.         /* convert format to 1 plane, 1 bit/pixel */ 
  294.         bm.bmPlanes = 1;
  295.         bm.bmBitsPixel = 1;
  296.         hdc_new = CreateCompatibleDC(hdc_bit);
  297.         hbitmap_new = CreateBitmap(bm.bmWidth, bm.bmHeight, bm.bmPlanes, bm.bmBitsPixel, NULL);
  298.         SelectBitmap(hdc_new, hbitmap_new);
  299.         hbitmap_old = SelectBitmap(hdc_bit, hbitmap);
  300.         BitBlt(hdc_new, 0, 0, bm.bmWidth, bm.bmHeight, hdc_bit, 0, 0, SRCCOPY);
  301.         SelectBitmap(hdc_bit, hbitmap_old);
  302.         DeleteDC(hdc_new);
  303.         hbitmap = hbitmap_new;
  304.     }
  305.      byte_width = (((bm.bmWidth * bm.bmBitsPixel + 31) & ~31) >> 3);
  306.     bitmap_size = (DWORD)bm.bmHeight *  byte_width;
  307.     palcolors = 1<<(bm.bmBitsPixel * bm.bmPlanes);
  308.     palsize = palcolors * sizeof(RGBQUAD);
  309.     hglobal = GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + palsize + bitmap_size);
  310.     if (hglobal != (HGLOBAL)NULL) {
  311.         lpBits = GlobalLock(hglobal);
  312.         pbmi = (LPBITMAPINFO)lpBits;
  313.         pbmih = (LPBITMAPINFOHEADER)lpBits;
  314.         lpBits += sizeof(BITMAPINFOHEADER) + palsize;
  315.         pbmih->biSize = sizeof(BITMAPINFOHEADER);
  316.         pbmih->biWidth = bm.bmWidth;
  317.         pbmih->biHeight = bm.bmHeight;
  318.         pbmih->biPlanes = 1;
  319.         pbmih->biBitCount = bm.bmBitsPixel * bm.bmPlanes;
  320.         pbmih->biCompression = BI_RGB;
  321.         pbmih->biSizeImage = bitmap_size;
  322.         pbmih->biXPelsPerMeter = (int)(xdpi / 25.4 * 1000);
  323.         pbmih->biYPelsPerMeter = (int)(ydpi / 25.4 * 1000);
  324.         pbmih->biClrUsed = palcolors;
  325.         pbmih->biClrImportant = palcolors;
  326.         /* create colour table from system palette */
  327.         pe = malloc(palcolors * sizeof(PALETTEENTRY));
  328.         if (IsClipboardFormatAvailable(CF_PALETTE)) {
  329.         HPALETTE hpalette = GetClipboardData(CF_PALETTE);
  330.         i = GetObject(hpalette, sizeof(int), pe);
  331.         GetPaletteEntries(hpalette, 0, i, pe);
  332.         }
  333.         else
  334.             GetSystemPaletteEntries(hdc_bit, 0, palcolors, pe);
  335.         for (i=0; i<palcolors; i++) {
  336.         pbmi->bmiColors[i].rgbRed = pe[i].peRed;
  337.         pbmi->bmiColors[i].rgbGreen = pe[i].peGreen;
  338.         pbmi->bmiColors[i].rgbBlue = pe[i].peBlue;
  339.         pbmi->bmiColors[i].rgbReserved = 0;
  340.         }
  341.         free((void *)pe);
  342.         i = GetDIBits(hdc_bit, hbitmap, 0, (UINT)pbmih->biHeight,
  343.         lpBits, pbmi, DIB_RGB_COLORS);
  344.         GlobalUnlock(hglobal);
  345.         if (i == 0) {
  346.         GlobalFree(hglobal);
  347.         hglobal = NULL;
  348.         }
  349.     }
  350.     DeleteDC(hdc_bit);
  351.     if (hbitmap != GetClipboardData(CF_BITMAP))
  352.         DeleteBitmap(hbitmap);
  353.     return hglobal;
  354. }
  355.  
  356. /* Read DDB from the clipboard, convert to DIB and add to clipboard */
  357. void
  358. clip_add_dib(void)
  359. {
  360. HGLOBAL hglobal;
  361.     hglobal = make_dib();
  362.     if (hglobal != (HGLOBAL)NULL)
  363.             SetClipboardData(CF_DIB, hglobal);
  364. }
  365.  
  366. /* extract temp PS file from EPS dfile */
  367. /* point dfile at temp PS file */
  368. void extract_eps(void)
  369. {
  370. DWORD pos;
  371. DWORD len;
  372. FILE *f;
  373. UINT count;
  374. char *buffer;
  375. DWORD dtemp;
  376.     rewind(dfile);
  377.     fread(&dtemp, 4, 1, dfile);    /* ignore ID */
  378.     fread(&pos, 4, 1, dfile);    /* PS offset */
  379.     fread(&len, 4, 1, dfile);    /* PS length */
  380.     fread(&dtemp, 4, 1, dfile);    /* Metafile offset */
  381.     if (dtemp != 0L)
  382.         preview = IDS_EPSW;
  383.     else {
  384.         fread(&dtemp, 4, 1, dfile);    /* Metafile length */
  385.         fread(&dtemp, 4, 1, dfile);    /* TIFF offset */
  386.         if (dtemp != 0L)
  387.             preview = IDS_EPST;
  388.     }
  389.     fseek(dfile, pos, SEEK_SET);    /* seek to PS section */
  390.     /* get new scratch file */
  391.     if ( (f = gp_open_scratch_file(szScratch, efname, "wb")) == (FILE *)NULL) {
  392.         play_sound(SOUND_ERROR);
  393.         return;
  394.     }
  395.     
  396.     /* create buffer for PS file copy */
  397.     buffer = malloc(COPY_BUF_SIZE);
  398.     if (buffer == (char *)NULL) {
  399.         play_sound(SOUND_ERROR);
  400.         fclose(f);
  401.         return;
  402.     }
  403.  
  404.         while ( (count = (UINT)min(len,COPY_BUF_SIZE)) != 0 ) {
  405.         count = fread(buffer, 1, count, dfile);
  406.         fwrite(buffer, 1, count, f);
  407.         len -= count;
  408.     }
  409.     free(buffer);
  410.     fclose(f);
  411.     fclose(dfile);
  412.     dfile = fopen(efname, "rb");
  413. }
  414.  
  415. typedef struct {
  416.     DWORD    key;
  417.     HMETAFILE    hmf;
  418.     RECT    bbox;
  419.     WORD    inch;
  420.     DWORD    reserved;
  421.     WORD    checksum;
  422. } METAFILEHEADER;
  423.  
  424. /* extract EPS or TIFF or WMF file from DOS EPS file */
  425. void extract_doseps(WORD command)
  426. {
  427. DWORD pos;
  428. DWORD len;
  429. UINT count;
  430. char *buffer;
  431. FILE* epsfile;
  432. BOOL is_meta = TRUE;
  433. char outname[MAXSTR];
  434. FILE *outfile;
  435. UINT filter;
  436.     if (!preview || (preview == IDS_EPSI)) {
  437.         gserror(IDS_NOPREVIEW, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  438.         return;
  439.     }
  440.     epsfile = fopen(dfname,"rb");
  441.     fread(&pos, 4, 1, epsfile);        /* ignore ID */
  442.     fread(&pos, 4, 1, epsfile);        /* PS offset */
  443.     fread(&len, 4, 1, epsfile);        /* PS length */
  444.     if (command == IDM_EXTRACTPRE) {
  445.         fread(&pos, 4, 1, epsfile);        /* Metafile offset */
  446.         fread(&len, 4, 1, epsfile);        /* Metafile length */
  447.         if (pos == 0L) {
  448.             fread(&pos, 4, 1, epsfile);    /* TIFF offset */
  449.             fread(&len, 4, 1, epsfile);    /* TIFF length */
  450.             is_meta = FALSE;
  451.         }
  452.     }
  453.     if (pos == 0L) {
  454.         fclose(epsfile);
  455.         gserror(IDS_NOPREVIEW, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  456.         return;
  457.     }
  458.     fseek(epsfile, pos, SEEK_SET);    /* seek to section to extract */
  459.  
  460.     /* create postscript or preview file */
  461.     outname[0] = '\0';
  462.     if (command == IDM_EXTRACTPRE) {
  463.         if (is_meta)
  464.             filter = FILTER_WMF;
  465.         else
  466.             filter = FILTER_TIFF;
  467.     }
  468.     else
  469.         filter = FILTER_EPS;
  470.     if (!getfilename(outname, SAVE, filter, NULL, IDS_TOPICEDIT)) {
  471.         fclose(epsfile);
  472.         return;
  473.     }
  474.  
  475.     outfile = fopen(outname, "wb");
  476.     if (outfile == (FILE *)NULL) {
  477.         play_sound(SOUND_ERROR);
  478.         fclose(epsfile);
  479.         return;
  480.     }
  481.     
  482.     /* create buffer for file copy */
  483.     buffer = malloc(COPY_BUF_SIZE);
  484.     if (buffer == (char *)NULL) {
  485.         play_sound(SOUND_ERROR);
  486.         fclose(epsfile);
  487.         fclose(outfile);
  488.         return;
  489.     }
  490.  
  491.     if ((command == IDM_EXTRACTPRE) && is_meta) {
  492.         /* write placeable Windows Metafile header */
  493.         METAFILEHEADER mfh;
  494.         int i;
  495.         WORD *pw;
  496.         mfh.key = 0x9ac6cdd7L;
  497.         mfh.hmf = 0;
  498.         mfh.bbox.left = 0;
  499.         mfh.bbox.right = doc->boundingbox[URX] - doc->boundingbox[LLX];
  500.         mfh.bbox.top = 0;
  501.         mfh.bbox.bottom = doc->boundingbox[URY] - doc->boundingbox[LLY];
  502.         mfh.inch = 72;    /* PostScript points */
  503.         mfh.reserved = 0L;
  504.         mfh.checksum =  0;
  505.         pw = (WORD *)&mfh;
  506.         for (i=0; i<10; i++) {
  507.             mfh.checksum ^= *pw++;
  508.         }
  509.         fwrite(&mfh, sizeof(mfh), 1, outfile);
  510.     }
  511.  
  512.         while ( (count = (UINT)min(len,COPY_BUF_SIZE)) != 0 ) {
  513.         count = fread(buffer, 1, count, epsfile);
  514.         fwrite(buffer, 1, count, outfile);
  515.         len -= count;
  516.     }
  517.     free(buffer);
  518.     fclose(epsfile);
  519.     fclose(outfile);
  520. }
  521.  
  522. /* convert a clipboard bitmap to a metafile picture */
  523. HMETAFILE
  524. make_metafile(void)
  525. {
  526. HDC hdc;
  527. HMETAFILE hmf;
  528. HGLOBAL hglobal;
  529.     if (IsClipboardFormatAvailable(CF_DIB)) {
  530.         LPBITMAPINFOHEADER pbmih;
  531.         BYTE _huge *lpDibBits;
  532.         hglobal = GetClipboardData(CF_DIB);
  533.         pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  534.         lpDibBits = ((BYTE _huge *)pbmih) + pbmih->biSize;
  535.         if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  536.         lpDibBits += dib_pal_colors(pbmih) * sizeof(RGBTRIPLE); 
  537.         else
  538.         lpDibBits += dib_pal_colors(pbmih) * sizeof(RGBQUAD); 
  539.         /* now make a Metafile from it */
  540.         hdc = CreateMetaFile(NULL);
  541.         SetWindowOrg(hdc, 0, 0);
  542.         SetWindowExt(hdc, (int)pbmih->biWidth, (int)pbmih->biHeight);
  543.         StretchDIBits(hdc, 0, 0, (int)pbmih->biWidth, (int)pbmih->biHeight,
  544.             0, 0, (int)pbmih->biWidth, (int)pbmih->biHeight,
  545.             (void FAR *)lpDibBits, (LPBITMAPINFO)pbmih,
  546.             DIB_RGB_COLORS, SRCCOPY);
  547.         hmf = CloseMetaFile(hdc);
  548.         GlobalUnlock(hglobal);
  549.     }
  550.     else if (IsClipboardFormatAvailable(CF_BITMAP)) {
  551.         HBITMAP hbitmap, hbitmap_old;
  552.         HDC hdc_bit;
  553.         BITMAP bm;
  554.         hbitmap = GetClipboardData(CF_BITMAP);
  555.         hdc = GetDC((HWND)NULL);
  556.         hdc_bit = CreateCompatibleDC(hdc);
  557.         ReleaseDC((HWND)NULL,hdc);
  558.         GetObject(hbitmap, sizeof(BITMAP), &bm);
  559.         hdc = CreateMetaFile(NULL);
  560.         SetWindowOrg(hdc, 0, 0);
  561.         SetWindowExt(hdc, bm.bmWidth, bm.bmHeight);
  562.         hbitmap_old = SelectBitmap(hdc_bit, hbitmap);
  563.         StretchBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight,
  564.             hdc_bit, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  565.         SelectBitmap(hdc_bit, hbitmap_old);
  566.         DeleteDC(hdc_bit);
  567.         hmf = CloseMetaFile(hdc);
  568.     }
  569.     else {
  570.         play_sound(SOUND_ERROR);
  571.         hmf = NULL;
  572.     }
  573.     return hmf;
  574. }
  575.  
  576. #ifdef NOT_USED
  577. /* not used */
  578. /* Read bitmap (CF_DIB or CF_BITMAP) from the clipboard */
  579. /* convert to Metafile Picture and add to clipboard */
  580. void
  581. clip_add_metafile(void)
  582. {
  583. LPMETAFILEPICT lpmfp;
  584. HGLOBAL hglobal;
  585. HMETAFILE hmf;
  586.     if ( (hmf = make_metafile()) == (HMETAFILE)NULL ) {
  587.         return;
  588.     }
  589.  
  590.     hglobal = GlobalAlloc(GHND | GMEM_SHARE, sizeof(METAFILEPICT)); 
  591.     lpmfp = GlobalLock(hglobal);
  592.     lpmfp->mm = MM_ANISOTROPIC;
  593.     if (bitmap_width)
  594.         lpmfp->xExt = (int)(bitmap_width / xdpi * 2540);
  595.     else 
  596.         lpmfp->xExt = 21000;    /* A4 */
  597.     if (bitmap_height)
  598.         lpmfp->yExt = (int)(bitmap_height / ydpi * 2540);
  599.     else
  600.         lpmfp->yExt = 29700;    /* A4 */
  601.     lpmfp->hMF = hmf;
  602.     GlobalUnlock(hglobal);
  603.     SetClipboardData(CF_METAFILEPICT, hglobal);
  604.     return;
  605. }
  606. #endif
  607.  
  608. struct eps_header_s {
  609.    char id[4];
  610.    DWORD ps_begin;
  611.    DWORD ps_length;
  612.    DWORD mf_begin;
  613.    DWORD mf_length;
  614.    DWORD tiff_begin;
  615.    DWORD tiff_length;
  616.    WORD  checksum;
  617. };
  618.  
  619. /* make a PC EPS file with a Windows Metafile Preview */
  620. /* from a PS file and a clipboard bitmap */
  621. void
  622. make_eps_metafile(void)
  623. {
  624. char epsname[MAXSTR];
  625. HMETAFILE hmf;
  626. HGLOBAL hglobal;
  627. char *buffer;
  628. UINT count;
  629. HFILE hfEPS;
  630. struct eps_header_s eps_header;
  631.  
  632.     if (!OpenClipboard(hwndimg)) {
  633.         play_sound(SOUND_ERROR);
  634.         return;
  635.     }
  636.  
  637.     if ( (hmf = make_metafile()) == (HMETAFILE)NULL ) {
  638.         play_sound(SOUND_ERROR);
  639.         CloseClipboard();
  640.         return;
  641.     }
  642.  
  643.     CloseClipboard();
  644.  
  645.     /* get memory handle to metafile */
  646.     hglobal = GetMetaFileBits(hmf);
  647.  
  648.     /* create buffer for PS file copy */
  649.     buffer = malloc(COPY_BUF_SIZE);
  650.     if (buffer == (char *)NULL) {
  651.         GlobalFree(hglobal);
  652.         gserror(IDS_BADEPS, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  653.         return;
  654.     }
  655.  
  656.     /* create EPS file */
  657.     epsname[0] = '\0';
  658.     if (!getfilename(epsname, SAVE, FILTER_EPS, NULL, IDS_TOPICEDIT)) {
  659.         GlobalFree(hglobal);
  660.         return;
  661.     }
  662.     hfEPS = _lcreat(epsname, 0);
  663.  
  664.     /* write DOS EPS binary header */
  665.     eps_header.id[0] = 0xc5;    /* "EPSF" with bit 7 set */
  666.     eps_header.id[1] = 0xd0;
  667.     eps_header.id[2] = 0xd3;
  668.     eps_header.id[3] = 0xc6;
  669.     eps_header.ps_begin = sizeof(eps_header);
  670.     fseek(dfile, 0, SEEK_END);
  671.     eps_header.ps_length = ftell(dfile);
  672.     eps_header.mf_begin = eps_header.ps_begin + eps_header.ps_length;
  673.     eps_header.mf_length = GlobalSize(hglobal);
  674.     eps_header.tiff_begin = 0;
  675.     eps_header.tiff_length = 0;
  676.     eps_header.checksum = -1;
  677.     _lwrite(hfEPS, (void _huge *)&eps_header, sizeof(eps_header));
  678.  
  679.     /* copy PS file */
  680.     rewind(dfile);
  681.     do {
  682.         count = fread(buffer, 1, COPY_BUF_SIZE, dfile);
  683.         _lwrite(hfEPS, buffer, count);
  684.     } while (count != 0);
  685.     free(buffer);
  686.  
  687.     /* copy metafile */
  688.     hwrite(hfEPS, GlobalLock(hglobal), eps_header.mf_length);
  689.     GlobalUnlock(hglobal);
  690.     GlobalFree(hglobal);
  691.  
  692.     _lclose(hfEPS);
  693. }
  694.  
  695.  
  696. char hex[16] = "0123456789ABCDEF";
  697. unsigned char isblack[256];
  698.  
  699. void
  700. scan_colors(LPBITMAPINFOHEADER pbmih)
  701. {
  702.     RGBQUAD FAR *prgbquad;
  703.     RGBTRIPLE FAR *prgbtriple;
  704.     unsigned char rr;
  705.     unsigned char gg;
  706.     unsigned char bb;
  707.     int isOS2 = FALSE;
  708.     int clrtablesize;
  709.     int i;
  710.  
  711.     prgbquad   = (RGBQUAD FAR *)(((BYTE _huge *)pbmih) + pbmih->biSize);
  712.     prgbtriple = (RGBTRIPLE FAR *)prgbquad;
  713.     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  714.         isOS2 = TRUE;
  715.     /* read in the color table */
  716.     clrtablesize = dib_pal_colors(pbmih);
  717.     for (i = 0; i < clrtablesize; i++) {
  718.         if (isOS2) {
  719.             bb = prgbtriple[i].rgbtBlue;
  720.             gg = prgbtriple[i].rgbtGreen;
  721.             rr = prgbtriple[i].rgbtRed;
  722.         }
  723.         else {
  724.             bb = prgbquad[i].rgbBlue;
  725.             gg = prgbquad[i].rgbGreen;
  726.             rr = prgbquad[i].rgbRed;
  727.         }
  728.         isblack[i] = (rr < 0xff) || (gg < 0xff) || (bb < 0xff);
  729.     }
  730. }
  731.  
  732. BYTE _huge *
  733. get_dib_bits(LPBITMAPINFOHEADER pbmih)
  734. {
  735. BYTE _huge *lpDibBits;
  736.     lpDibBits = (((BYTE _huge *)pbmih) + pbmih->biSize);
  737.     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  738.         lpDibBits += dib_pal_colors(pbmih) * sizeof(RGBTRIPLE); 
  739.     else
  740.         lpDibBits += dib_pal_colors(pbmih) * sizeof(RGBQUAD); 
  741.     return lpDibBits;
  742. }
  743.  
  744. void
  745. get_dib_line(BYTE _huge *line, char *preview, int width, int bitcount)
  746. {
  747. int bwidth = ((width + 7) & ~7) >> 3; /* byte width with 1 bit/pixel */
  748. unsigned char omask;
  749. int oroll;
  750. unsigned char c = 0;
  751. int j;
  752.     memset(preview,0xff,bwidth);
  753.     omask = 0x80;
  754.     oroll = 7;
  755.     if (bitcount == 1) {
  756.         if (isblack[0])
  757.         for (j = 0; j < bwidth ; j++)
  758.             preview[j] = line[j];
  759.         else
  760.         for (j = 0; j < bwidth ; j++)
  761.             preview[j] = ~line[j];
  762.         preview[bwidth-1] |= width & 7 ? (1<<(8-(width&7)))-1 : 0;    /* mask for edge of bitmap */
  763.     }
  764.     else {
  765.         for (j = 0; j < width; j++) {
  766.         switch (bitcount) {
  767.             case 4:
  768.                 c = line[j>>1];
  769.                 if (!(j&1))
  770.                     c >>= 4;
  771.                 c = isblack[ c & 0x0f ];
  772.                 break;
  773.             case 8:
  774.                 c = isblack[ (int)(line[j]) ];
  775.                 break;
  776.             case 24:
  777.                 c = (line[j*3] < 0xff) || 
  778.                     (line[j*3+1] < 0xff) || 
  779.                     (line[j*3+2] < 0xff);
  780.                 break;
  781.         }
  782.         if (c) 
  783.             preview[j/8] &= ~omask;
  784.         else
  785.             preview[j/8] |= omask;
  786.         oroll--;
  787.         omask >>= 1;
  788.         if (oroll < 0) {
  789.             omask = 0x80;
  790.             oroll = 7;
  791.         }
  792.         }
  793.     }
  794. }
  795.  
  796. #define TIFF_BYTE 1
  797. #define TIFF_ASCII 2
  798. #define TIFF_SHORT 3
  799. #define TIFF_LONG 4
  800. #define TIFF_RATIONAL 5
  801.  
  802. struct rational_s {
  803.     DWORD numerator;
  804.     DWORD denominator;
  805. };
  806.  
  807. struct ifd_entry_s {
  808.     WORD tag;
  809.     WORD type;
  810.     DWORD length;
  811.     DWORD value;
  812. };
  813.  
  814. struct tiff_head_s {
  815.     WORD order;
  816.     WORD version;
  817.     DWORD ifd_offset;
  818.     WORD ifd_length;
  819. };
  820.  
  821. /* write tiff file from DIB bitmap */
  822. /* hglobal is handle to DIB in memory */
  823. void
  824. write_tiff(FILE *f, HGLOBAL hglobal, BOOL tiff4)
  825. {
  826. char *now;
  827. DWORD *strip;
  828. #define IFD_MAX_ENTRY 12
  829. struct tiff_head_s tiff_head;
  830. WORD ifd_length;
  831. DWORD ifd_next;
  832. struct ifd_entry_s ifd_entry[IFD_MAX_ENTRY];
  833. struct ifd_entry_s *pifd_entry;
  834. struct rational_s rational;
  835. DWORD tiff_end, end;
  836. time_t t;
  837. int i;
  838. char *preview;
  839. LPBITMAPINFOHEADER pbmih;
  840. BYTE _huge *lpDibBits;
  841. BYTE _huge *line;
  842. int width;
  843. int height;
  844. int bitcount;
  845. int bwidth;
  846. BOOL soft_extra = FALSE;
  847. BOOL date_extra = FALSE;
  848.  
  849.     pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  850.     lpDibBits = get_dib_bits(pbmih);
  851.  
  852.     width = (int)pbmih->biWidth;
  853.     height = (int)pbmih->biHeight;
  854.     bitcount = pbmih->biBitCount;
  855.     /* byte width with 1 bit/pixel, rounded up even word */
  856.     bwidth = ((width + 15) & ~15) >> 3;
  857.     height = (int)pbmih->biHeight;
  858.  
  859.     tiff_end = sizeof(tiff_head);
  860.     tiff_head.order = 0x4949;
  861.     tiff_head.version = 42;
  862.     tiff_head.ifd_offset = tiff_end;
  863.  
  864.     tiff_end += sizeof(ifd_length);
  865.  
  866.     if (tiff4)
  867.         ifd_length = 10;
  868.     else
  869.         ifd_length = 12;
  870.  
  871.     tiff_end += ifd_length * sizeof(struct ifd_entry_s) + sizeof(ifd_next);
  872.     ifd_next = 0;
  873.     pifd_entry = &ifd_entry[0];
  874.     if (tiff4) {
  875.         pifd_entry->tag = 0xff;    /* SubfileType */
  876.         pifd_entry->type = TIFF_SHORT;
  877.     }
  878.     else {
  879.         pifd_entry->tag = 0xfe;    /* NewSubfileType */
  880.         pifd_entry->type = TIFF_LONG;
  881.     }
  882.     pifd_entry->length = 1;
  883.     pifd_entry->value = 0;
  884.  
  885.     pifd_entry = &ifd_entry[1];
  886.     pifd_entry->tag = 0x100;    /* ImageWidth */
  887.     if (tiff4)
  888.         pifd_entry->type = TIFF_SHORT;
  889.     else
  890.         pifd_entry->type = TIFF_LONG;
  891.     pifd_entry->length = 1;
  892.     pifd_entry->value = pbmih->biWidth;
  893.  
  894.     pifd_entry = &ifd_entry[2];
  895.     pifd_entry->tag = 0x101;    /* ImageLength */
  896.     if (tiff4)
  897.         pifd_entry->type = TIFF_SHORT;
  898.     else
  899.         pifd_entry->type = TIFF_LONG;
  900.     pifd_entry->length = 1;
  901.     pifd_entry->value = height;
  902.  
  903.     pifd_entry = &ifd_entry[3];
  904.     pifd_entry->tag = 0x103;    /* Compression */
  905.     pifd_entry->type = TIFF_SHORT;
  906.     pifd_entry->length = 1;
  907.     pifd_entry->value = 1;        /* no compression */
  908.  
  909.     pifd_entry = &ifd_entry[4];
  910.     pifd_entry->tag = 0x106;    /* PhotometricInterpretation */
  911.     pifd_entry->type = TIFF_SHORT;
  912.     pifd_entry->length = 1;
  913.     pifd_entry->value = 1;        /* black is zero */
  914.  
  915.     pifd_entry = &ifd_entry[5];
  916.     pifd_entry->tag = 0x111;    /* StripOffsets */
  917.     pifd_entry->type = TIFF_LONG;
  918.     pifd_entry->length = height;
  919.     pifd_entry->value = tiff_end;
  920.     tiff_end += (pifd_entry->length * sizeof(DWORD));
  921.  
  922.     pifd_entry = &ifd_entry[6];
  923.     pifd_entry->tag = 0x116;    /* RowsPerStrip */
  924.     pifd_entry->type = TIFF_LONG;
  925.     pifd_entry->length = 1;
  926.     pifd_entry->value = 1;
  927.  
  928.     pifd_entry = &ifd_entry[7];
  929.     pifd_entry->tag = 0x117;    /* StripByteCounts */
  930.     pifd_entry->type = TIFF_LONG;
  931.     pifd_entry->length = height;
  932.     pifd_entry->value = tiff_end;
  933.     tiff_end += (pifd_entry->length * sizeof(DWORD));
  934.  
  935.     pifd_entry = &ifd_entry[8];
  936.     pifd_entry->tag = 0x11a;    /* XResolution */
  937.     pifd_entry->type = TIFF_RATIONAL;
  938.     pifd_entry->length = 1;
  939.     pifd_entry->value = tiff_end;
  940.     tiff_end += sizeof(struct rational_s);
  941.  
  942.     pifd_entry = &ifd_entry[9];
  943.     pifd_entry->tag = 0x11b;    /* YResolution */
  944.     pifd_entry->type = TIFF_RATIONAL;
  945.     pifd_entry->length = 1;
  946.     pifd_entry->value = tiff_end;
  947.     tiff_end += sizeof(struct rational_s);
  948.  
  949.     if (!tiff4) {
  950.         pifd_entry = &ifd_entry[10];
  951.         pifd_entry->tag = 0x131;    /* Software */
  952.         pifd_entry->type = TIFF_ASCII;
  953.         pifd_entry->length = strlen(szAppName) + 1;
  954.         pifd_entry->value = tiff_end;
  955.         tiff_end += pifd_entry->length;
  956.         if (tiff_end & 1) { /* pad to word boundary */
  957.             soft_extra = TRUE;
  958.             tiff_end++;
  959.         }
  960.  
  961.         pifd_entry = &ifd_entry[11];
  962.         pifd_entry->tag = 0x132;    /* DateTime */
  963.         pifd_entry->type = TIFF_ASCII;
  964.         t = time(NULL);
  965.         now = ctime(&t);
  966.         now[strlen(now)-1] = '\0';    /* remove trailing \n */
  967.         pifd_entry->length = strlen(now)+1;
  968.         pifd_entry->value = tiff_end;
  969.         tiff_end += pifd_entry->length;
  970.         if (tiff_end & 1) { /* pad to word boundary */
  971.             date_extra = TRUE;
  972.             tiff_end++;
  973.         }
  974.     }
  975.  
  976.     fwrite(&tiff_head, sizeof(tiff_head), 1, f);
  977.     fwrite(&ifd_length, sizeof(ifd_length), 1, f);
  978.     fwrite(&ifd_entry, ifd_length * sizeof(struct ifd_entry_s), 1, f);
  979.     fwrite(&ifd_next, sizeof(ifd_next), 1, f);
  980.     strip = (DWORD *)malloc(height * sizeof(DWORD));
  981.     end = tiff_end;
  982.     for (i=0; i<height; i++) {
  983.         strip[i] = end;        /* strip offsets */
  984.         end += bwidth;
  985.     }
  986.     fwrite(strip, 1, height * sizeof(DWORD), f);
  987.     for (i=0; i<height; i++)
  988.         strip[i] = bwidth;    /* strip byte counts */
  989.     fwrite(strip, 1, height * sizeof(DWORD), f);
  990.     free((void *)strip);
  991.     rational.numerator = (int)xdpi;
  992.     rational.denominator = 1;
  993.     fwrite(&rational, sizeof(rational), 1, f);
  994.     rational.numerator = (int)ydpi;
  995.     rational.denominator = 1;
  996.     fwrite(&rational, sizeof(rational), 1, f);
  997.     if (!tiff4) {
  998.         fwrite(szAppName, 1, strlen(szAppName)+1, f);
  999.         if (soft_extra)
  1000.             fputc('\0',f);
  1001.         fwrite(now, 1, strlen(now)+1, f);
  1002.         if (date_extra)
  1003.             fputc('\0',f);
  1004.     }
  1005.  
  1006.     scan_colors(pbmih);
  1007.  
  1008.     preview = (char *) malloc(bwidth);
  1009.     memset(preview,0xff,bwidth);
  1010.  
  1011.     line = lpDibBits + (dib_bytewidth(pbmih) * pbmih->biHeight);
  1012.     /* process each line of bitmap */
  1013.     for (i = 0; i < pbmih->biHeight; i++) {
  1014.         line -= dib_bytewidth(pbmih);
  1015.         get_dib_line(line, preview, width, bitcount);
  1016.         fwrite(preview, 1, bwidth, f);
  1017.     }
  1018.     free(preview);
  1019.     GlobalUnlock(hglobal);
  1020. }
  1021.  
  1022. /* make a PC EPS file with a TIFF Preview */
  1023. /* from a PS file and a clipboard bitmap */
  1024. void
  1025. make_eps_tiff(WORD type)
  1026. {
  1027. char epsname[MAXSTR];
  1028. HGLOBAL hglobal;
  1029. char *buffer;
  1030. UINT count;
  1031. FILE *epsfile;
  1032. FILE *tiff_file;
  1033. char tiffname[MAXSTR];
  1034. BOOL made_dib = FALSE;
  1035. struct eps_header_s eps_header;
  1036.  
  1037.     if (!OpenClipboard(hwndimg)) {
  1038.         play_sound(SOUND_ERROR);
  1039.         return;
  1040.     }
  1041.     if (IsClipboardFormatAvailable(CF_DIB))
  1042.         hglobal = GetClipboardData(CF_DIB);
  1043.     else if (IsClipboardFormatAvailable(CF_BITMAP)) {
  1044.         /* untested */
  1045.         hglobal = make_dib(); /* convert to DIB format */
  1046.         if (hglobal == (HGLOBAL)NULL) {
  1047.             play_sound(SOUND_ERROR);
  1048.             CloseClipboard();
  1049.             return;
  1050.         }
  1051.         made_dib = TRUE;
  1052.     }
  1053.     else {
  1054.         play_sound(SOUND_ERROR);
  1055.         CloseClipboard();
  1056.         return;
  1057.     }
  1058.     
  1059.     if ( (tiff_file = gp_open_scratch_file(szScratch, tiffname, "wb")) == (FILE *)NULL) {
  1060.         play_sound(SOUND_ERROR);
  1061.         if (made_dib)
  1062.             GlobalFree(hglobal);
  1063.         CloseClipboard();
  1064.         return;
  1065.     }
  1066.     write_tiff(tiff_file, hglobal, (type == IDM_MAKEEPST4));
  1067.     fclose(tiff_file);
  1068.     CloseClipboard();
  1069.     if (made_dib)
  1070.         GlobalFree(hglobal);
  1071.  
  1072.     /* create EPS file */
  1073.     epsname[0] = '\0';
  1074.     if (!getfilename(epsname, SAVE, FILTER_EPS, NULL, IDS_TOPICEDIT)) {
  1075.         unlink(tiffname);
  1076.         return;
  1077.     }
  1078.     epsfile = fopen(epsname,"wb");
  1079.  
  1080.     /* write DOS EPS binary header */
  1081.     eps_header.id[0] = 0xc5;
  1082.     eps_header.id[1] = 0xd0;
  1083.     eps_header.id[2] = 0xd3;
  1084.     eps_header.id[3] = 0xc6;
  1085.     eps_header.ps_begin = sizeof(eps_header);
  1086.     fseek(dfile, 0, SEEK_END);
  1087.     eps_header.ps_length = ftell(dfile);
  1088.     eps_header.mf_begin = 0;
  1089.     eps_header.mf_length = 0;
  1090.     eps_header.tiff_begin = eps_header.ps_begin + eps_header.ps_length;
  1091.     tiff_file = fopen(tiffname,"rb");
  1092.     fseek(tiff_file, 0, SEEK_END);
  1093.     eps_header.tiff_length = ftell(tiff_file);;
  1094.     eps_header.checksum = -1;
  1095.  
  1096.     fwrite(&eps_header, sizeof(eps_header), 1, epsfile);
  1097.     rewind(dfile);
  1098.     pscopy(dfile, epsfile, doc->beginheader, doc->endtrailer);
  1099.     
  1100.     /* copy tiff file */
  1101.     rewind(tiff_file);
  1102.     buffer = malloc(COPY_BUF_SIZE);
  1103.     if (buffer == (char *)NULL) {
  1104.         play_sound(SOUND_ERROR);
  1105.         fclose(epsfile);
  1106.         unlink(epsname);
  1107.         fclose(tiff_file);
  1108.         unlink(tiffname);
  1109.         return;
  1110.     }
  1111.         while ( (count = fread(buffer, 1, COPY_BUF_SIZE, tiff_file)) != 0 )
  1112.         fwrite(buffer, 1, count, epsfile);
  1113.     free(buffer);
  1114.     fclose(tiff_file);
  1115.     unlink(tiffname);
  1116.     fclose(epsfile);
  1117. }
  1118.  
  1119.  
  1120. /* write interchange preview to file f */
  1121. /* hglobal is handle to DIB in memory */
  1122. void
  1123. write_interchange(FILE *f, HGLOBAL hglobal)
  1124. {
  1125.     int i, j;
  1126.     char *preview;
  1127.     LPBITMAPINFOHEADER pbmih;
  1128.     BYTE _huge *lpDibBits;
  1129.     BYTE _huge *line;
  1130.     int width;
  1131.     int height;
  1132.     int bitcount;
  1133.     int bwidth;
  1134.     int lines_per_scan;
  1135.     
  1136.     pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  1137.     lpDibBits = get_dib_bits(pbmih);
  1138.  
  1139.     width = (int)pbmih->biWidth;
  1140.     height = (int)pbmih->biHeight;
  1141.     bitcount = pbmih->biBitCount;
  1142.     bwidth = ((width + 7) & ~7) >> 3; /* byte width with 1 bit/pixel */
  1143.  
  1144.     scan_colors(pbmih);
  1145.  
  1146.     preview = (char *) malloc(bwidth);
  1147.  
  1148.     lines_per_scan = ((bwidth-1) / 32) + 1;
  1149.     fprintf(f,"%%%%BeginPreview: %u %u 1 %u\r\n",width, height, 
  1150.         height*lines_per_scan);
  1151.  
  1152.     line = lpDibBits + (dib_bytewidth(pbmih) * pbmih->biHeight);
  1153.     /* process each line of bitmap */
  1154.     for (i = 0; i < pbmih->biHeight; i++) {
  1155.         line -= dib_bytewidth(pbmih);
  1156.         get_dib_line(line, preview, width, bitcount);
  1157.         fputs("% ",f);
  1158.         for (j=0; j<bwidth; j++) {
  1159.             if (j && ((j & 31) == 0))
  1160.                 fputs("\r\n% ",f);
  1161.             fputc(hex[15-((preview[j]>>4)&15)],f);
  1162.             fputc(hex[15-((preview[j])&15)],f);
  1163.         }
  1164.         fputs("\r\n",f);
  1165.     }
  1166.  
  1167.     fputs("%%EndPreview\r\n",f);
  1168.     free(preview);
  1169.     GlobalUnlock(hglobal);
  1170. }
  1171.  
  1172. /* make an EPSI file with an Interchange Preview */
  1173. /* from a PS file and a clipboard bitmap */
  1174. void
  1175. make_eps_interchange(void)
  1176. {
  1177. HGLOBAL hglobal;
  1178. char epiname[MAXSTR];
  1179. FILE *epifile;
  1180. BOOL made_dib = FALSE;
  1181.     if (!OpenClipboard(hwndimg)) {
  1182.         play_sound(SOUND_ERROR);
  1183.         return;
  1184.     }
  1185.     if (IsClipboardFormatAvailable(CF_DIB))
  1186.         hglobal = GetClipboardData(CF_DIB);
  1187.     else if (IsClipboardFormatAvailable(CF_BITMAP)) {
  1188.         /* untested */
  1189.         hglobal = make_dib(); /* convert to DIB format */
  1190.         if (hglobal == (HGLOBAL)NULL) {
  1191.             play_sound(SOUND_ERROR);
  1192.             CloseClipboard();
  1193.             return;
  1194.         }
  1195.         made_dib = TRUE;
  1196.     }
  1197.     else {
  1198.         play_sound(SOUND_ERROR);
  1199.         CloseClipboard();
  1200.         return;
  1201.     }
  1202.  
  1203.     /* create EPI file */
  1204.     epiname[0] = '\0';
  1205.     if (!getfilename(epiname, SAVE, FILTER_EPI, NULL, IDS_TOPICEDIT)) {
  1206.         play_sound(SOUND_ERROR);
  1207.         CloseClipboard();
  1208.         return;
  1209.     }
  1210.  
  1211.     if ((epifile = fopen(epiname,"wb")) == (FILE *)NULL) {
  1212.         play_sound(SOUND_ERROR);
  1213.         if (made_dib)
  1214.             GlobalFree(hglobal);
  1215.         CloseClipboard();
  1216.         return;
  1217.     }
  1218.  
  1219.     rewind(dfile);
  1220.     pscopy(dfile, epifile, doc->beginheader, doc->endheader);
  1221.     write_interchange(epifile,hglobal);
  1222.     pscopy(dfile, epifile, doc->endheader, doc->endtrailer);
  1223.     fclose(epifile);
  1224.     if (made_dib)
  1225.         GlobalFree(hglobal);
  1226.     CloseClipboard();
  1227. }
  1228.  
  1229.  
  1230. int bbox[4];
  1231. BOOL bbflag;
  1232.  
  1233. BOOL CALLBACK _export
  1234. BoundingBoxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1235. {
  1236. static int bboxindex;
  1237. int x, y;
  1238. char buf[MAXSTR];
  1239.     switch(message) {
  1240.     case WM_INITDIALOG:
  1241.         bboxindex = 0;
  1242.         LoadString(phInstance, IDS_BBPROMPT, buf, sizeof(buf));
  1243.         SetDlgItemText(hDlg, BB_PROMPT, buf);
  1244.         return TRUE;
  1245.     case WM_COMMAND:
  1246.         switch(LOWORD(wParam)) {
  1247.         case BB_CLICK:
  1248.             if (!get_cursorpos(&x, &y)) {
  1249.             DestroyWindow(hDlg);
  1250.             hDlgModeless = 0;
  1251.             }
  1252.             switch(bboxindex) {
  1253.             case LLX:
  1254.             case URX:
  1255.                 bbox[bboxindex] = x;
  1256.                 break;
  1257.             case URY:
  1258.                 bbflag = TRUE;
  1259.             case LLY:
  1260.                 bbox[bboxindex] = y;
  1261.                 break;
  1262.             }
  1263.             bboxindex++;
  1264.             if (bboxindex <= URY) {
  1265.                     LoadString(phInstance, IDS_BBPROMPT+bboxindex, buf, sizeof(buf));
  1266.                     SetDlgItemText(hDlg, BB_PROMPT, buf);
  1267.             return FALSE;
  1268.             }
  1269.         case WM_CLOSE:
  1270.         case IDCANCEL:
  1271.             DestroyWindow(hDlg);
  1272.             hDlgModeless = 0;
  1273.             return TRUE;
  1274.         }
  1275.     }
  1276.     return FALSE;
  1277. }
  1278.  
  1279. BOOL
  1280. get_bbox(void)
  1281. {
  1282. DLGPROC lpfnBoundingBoxProc;
  1283.  
  1284.     bbflag = FALSE;
  1285.     bbox[LLX] = bbox[LLY] = bbox[URX] = bbox[URY] = 0;
  1286.     if (!page_ready) {
  1287.         gserror(IDS_EPSNOBBOX, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  1288.         return FALSE;
  1289.     }
  1290.     lpfnBoundingBoxProc = (DLGPROC)MakeProcInstance((FARPROC)BoundingBoxDlgProc, phInstance);
  1291.     hDlgModeless = CreateDialogParam(phInstance, "BoundingBoxDlgBox", hwndimg, lpfnBoundingBoxProc, (LPARAM)NULL);
  1292.     while (hDlgModeless) {
  1293.         do_message();    /* wait for bounding box to be obtained */
  1294.     }
  1295.     FreeProcInstance((FARPROC)lpfnBoundingBoxProc);
  1296.     return bbflag;
  1297. }
  1298.  
  1299.  
  1300. /* At present only allows bounding box to be specified */
  1301. void
  1302. ps_to_eps(void)
  1303. {
  1304. char output[MAXSTR];
  1305. FILE *f;
  1306. char *buffer;
  1307. UINT count;
  1308. FILE *infile;
  1309. time_t t;
  1310. char *now;
  1311. char text[PSLINELENGTH];
  1312. char *comment;
  1313. long here;
  1314.  
  1315.     LoadString(phInstance, IDS_EPSREAD, output, sizeof(output));
  1316.     if (MessageBox(hwndimg, output, szAppName, MB_YESNO | MB_ICONQUESTION)
  1317.         != IDYES) {
  1318.         LoadString(phInstance, IDS_TOPICPSTOEPS, szHelpTopic, sizeof(szHelpTopic));
  1319.         SendMessage(hwndimg, help_message, 0, 0L);
  1320.         return;
  1321.     }
  1322.  
  1323.     if (!hwndimgchild || !IsWindow(hwndimgchild)) {
  1324.         gserror(IDS_EPSNOBBOX, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  1325.         return;
  1326.     }
  1327.  
  1328.     if ((doc != (struct document *)NULL) && (doc->numpages > 1)) {
  1329.         gserror(IDS_EPSONEPAGE, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  1330.         return;
  1331.     }
  1332.     if (doc == (struct document *)NULL) {
  1333.         char mess[MAXSTR];
  1334.         LoadString(phInstance, IDS_EPSQPAGES, mess, sizeof(mess));
  1335.         if (MessageBox(hwndimg, mess, szAppName, MB_YESNO | MB_ICONQUESTION) != IDYES)
  1336.         return;
  1337.     }
  1338.  
  1339.     if (!get_bbox()) {
  1340.         play_sound(SOUND_ERROR);
  1341.         return;
  1342.     }
  1343.  
  1344.     output[0] = '\0';
  1345.     if (!getfilename(output, SAVE, FILTER_EPS, NULL, IDS_TOPICPSTOEPS))
  1346.         return;
  1347.  
  1348.     if ((f = fopen(output, "wb")) == (FILE *)NULL) {
  1349.         play_sound(SOUND_ERROR);
  1350.         return;
  1351.     }
  1352.  
  1353.     if (doc == (struct document *)NULL) {
  1354.         info_wait(TRUE);
  1355.         fputs("%!PS-Adobe-3.0 EPSF-3.0\r\n",f);
  1356.         /* if this is not a single page document then gsview has just lied */
  1357.         fprintf(f, "%%%%BoundingBox: %u %u %u %u\r\n",
  1358.         bbox[LLX],bbox[LLY],bbox[URX],bbox[URY]);
  1359.         fprintf(f,"%%%%Title: %s\r\n",dfname);
  1360.         fprintf(f,"%%%%Creator: %s from %s\r\n",szAppName,dfname);
  1361.         t = time(NULL);
  1362.         now = ctime(&t);
  1363.         now[strlen(now)-1] = '\0';    /* remove trailing \n */
  1364.         fprintf(f,"%%%%CreationDate: %s\r\n",now);
  1365.         fputs("%%Pages: 1\r\n",f);
  1366.         fputs("%%EndComments\r\n",f);
  1367.  
  1368.         fputs("%%Page: 1 1\r\n",f);
  1369.         fprintf(f,"%%BeginDocument: %s\r\n",dfname);
  1370.  
  1371.         /* create buffer for PS file copy */
  1372.         buffer = malloc(COPY_BUF_SIZE);
  1373.         if (buffer == (char *)NULL) {
  1374.             play_sound(SOUND_ERROR);
  1375.             fclose(f);
  1376.         unlink(output);
  1377.             return;
  1378.         }
  1379.  
  1380.         infile = fopen(dfname, "rb");
  1381.         if (infile == (FILE *)NULL) {
  1382.             play_sound(SOUND_ERROR);
  1383.             fclose(f);
  1384.         unlink(output);
  1385.             return;
  1386.         }
  1387.  
  1388.             while ( (count = fread(buffer, 1, COPY_BUF_SIZE, infile)) != 0 ) {
  1389.             fwrite(buffer, 1, count, f);
  1390.         }
  1391.         free(buffer);
  1392.         fclose(infile);
  1393.  
  1394.         fputs("%%EndDocument\r\n",f);
  1395.         fputs("%%Trailer\r\n",f);
  1396.         fclose(f);
  1397.         info_wait(FALSE);
  1398.     }
  1399.     else {
  1400.         /* document already has DSC comments */
  1401.         info_wait(TRUE);
  1402.         rewind(dfile);
  1403.         if (is_ctrld)
  1404.             fgetc(dfile);
  1405.         fgets(text, PSLINELENGTH, dfile);
  1406.         if (doc->epsf)
  1407.             fputs(text,f);
  1408.         else
  1409.             fputs("%!PS-Adobe-3.0 EPSF-3.0\r\n",f);
  1410.         if ((doc->boundingbox[LLX] != 0) || (doc->boundingbox[LLY] != 0) || 
  1411.             (doc->boundingbox[URX] != 0) || (doc->boundingbox[URY] != 0)) {
  1412.             if ( (comment = pscopyuntil(dfile, f, -1,
  1413.                doc->endheader, "%%BoundingBox:")) != (char *)NULL ) {
  1414.             free(comment);
  1415.             }
  1416.         }
  1417.         fprintf(f, "%%%%BoundingBox: %u %u %u %u\r\n",
  1418.         bbox[LLX],bbox[LLY],bbox[URX],bbox[URY]);
  1419.         here = ftell(dfile);
  1420.         pscopy(dfile, f, here, doc->endtrailer);
  1421.         fclose(f);
  1422.         info_wait(FALSE);
  1423.     }
  1424. }
  1425.